package com.llu.serial.fastjson;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

/**
 * FieldInfo 类用于存储特定类字段的信息，包括字段名称、反射 Field 和 Method 对象、基本类型以及泛型类型。
 * 该类主要便于执行字段的 getter 和 setter 操作，在涉及反射和泛型处理的场景中特别有用。
 */
public class FieldInfo {

    // 字段名称
    public String name;
    // 反射 Field 对象，用于直接操作字段
    public Field field;
    // 反射 Method 对象，通常对应字段的 getter 或 setter 方法
    public Method method;
    // 字段的基本数据类型，由方法的返回类型或字段本身的类型决定
    public Class type;

    // 字段的泛型类型，主要用于涉及泛型的字段
    public Type genericType;

    /**
     * 构造函数，使用名称、方法和字段初始化 FieldInfo 对象。
     * @param name 字段的名称
     * @param method 与字段相关的 Method 对象
     * @param field 与字段相关的 Field 对象
     */
    public FieldInfo(String name, Method method, Field field){
        this(name, method, field, false);
    }

    /**
     * 构造函数，使用名称、方法、字段以及是否为 setter 方法来初始化 FieldInfo 对象。
     * @param name 字段的名称
     * @param method 与字段相关的 Method 对象
     * @param field 与字段相关的 Field 对象
     * @param isSetter 是否为 setter 方法
     */
    public FieldInfo(String name, Method method, Field field, boolean isSetter) {
        // 设置当前实例的 name 属性值
        this.name = name;
        // 设置当前实例的 field 属性值
        this.field = field;
        // 设置当前实例的 method 属性值
        this.method = method;
        // 对应 Key 的 Value 类型
        // 根据 method 或 field 确定 type 的类型
        type = method != null ? method.getReturnType() : field.getType();
        // 判断是否为 setter 方法
        if(isSetter){
            // 当我们采集 set 函数的时候，实际上已经过滤了有且只有一个参数的函数
            // 确定 genericType 的类型
            if(null != method){
                genericType = method.getGenericParameterTypes()[0];
            }else{
                genericType = field.getGenericType();
            }
        }
    }

    /**
     * 获取字段的值。
     * @param object 包含目标字段的对象实例
     * @return 字段的值
     */
    public Object get(Object object) {
        try {
            return method != null ? method.invoke(object) : field.get(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 设置字段的值。
     * @param object 包含目标字段的对象实例
     * @param value 要设置的新值
     */
    public void set(Object object, Object value) {
        try {
            if (method != null) {
                method.invoke(object, value);
            } else {
                field.set(object, value);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
